package gui;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import common.EarthSimSettings;
import common.IGrid;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class CellValueWindow extends JFrame implements ActionListener {
  private static final long serialVersionUID = 5646347170408826418L;
  private EarthSimSettings settings = EarthSimSettings.getInstance();
  private final String NEXT = "Next";
  private final String PREV = "Prev";
  private JPanel cards;
  private JButton btnNext;
  private JButton btnPrev;
  private String[] cardNames;
  private int cardIndex;
  private int numRows;
  private int numCols;
  private String[] columnNames;
  private JLabel lblTime;
  private DateFormat dateFormat;
  JScrollPane scrollPane;
  private JPanel[] tables;
  
  public CellValueWindow() {
    super("Cell Values");
    dateFormat = new SimpleDateFormat("EEE, MMM d, yyyy HH:mm z Z");
    dateFormat.setTimeZone(settings.getTimeZone());
    
    List grids = settings.getCachedGrids();
    IGrid grid = (IGrid) grids.get(0);
    
    numRows = grid.getHeight();
    numCols = grid.getWidth();
    
    columnNames = new String[numCols];
    int currentCell = 0;
    for(int i = 0; i < numCols; i++) {
      String name = currentCell + "-" + (currentCell + grid.getGridSpacing());
      columnNames[i] = name;
      currentCell += grid.getGridSpacing();
    }
    
    JPanel pnlMain = new JPanel();
    pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.PAGE_AXIS));    
    pnlMain.add(getControls());
    
    cards = new JPanel(new CardLayout());
    addCards();
    pnlMain.add(cards);
    
    //Create and set up the content pane.
//    pnlMain.setOpaque(true); //content panes must be opaque    
//    setContentPane(pnlMain);
    Container pane = getContentPane();
    pane.add(getControls(), BorderLayout.PAGE_START);
    pane.add(cards, BorderLayout.CENTER);
  }
  
  public void addCards() {
    /*
     * This needs to be changed. There are too many grids and it causes an out of memory error to try and store
     * a card for each of them. Instead just store a reference to the grid list and get each grid and update the
     * gui when it is requested by the user
     * */
     
    List grids = settings.getCachedGrids();    
    tables = new JPanel[grids.size()];
    cardNames = new String[grids.size()];
    
    //hack until this implementation is fixed; obviously the table won't change when the user hits next/prev
    Object[][] dataHack = new Object[numRows][numCols];
    IGrid gridHack = (IGrid) grids.get(grids.size()-1); 
    for(int y = 0; y < numRows; y++) {
      for(int x = 0; x < numCols; x++) {
        dataHack[y][x] = new Float(gridHack.getTemperature(x, y));
      }
    }
    JTable table = new JTable(dataHack, columnNames);
    table.setPreferredScrollableViewportSize(new Dimension(500, 70));
    //end hack

    for(int i = 0; i < grids.size(); i++) {
      IGrid grid = (IGrid) grids.get(i);
//      Object[][] data = new Object[numRows][numCols];
//      for(int y = 0; y < numRows; y++) {
//        for(int x = 0; x < numCols; x++) {
//          data[y][x] = new Float(grid.getTemperature(x, y));
//        }
//      }
      String cardName = String.valueOf(grid.getTime());
      
//      JTable table = new JTable(data, columnNames);
//      table.setPreferredScrollableViewportSize(new Dimension(500, 70));
  
      scrollPane = new JScrollPane(table);
      JPanel pnlGrid = new JPanel(new GridLayout(1,0));
      pnlGrid.add(scrollPane);
      
      cards.add(pnlGrid, cardName);
      tables[i] = pnlGrid;
      cardNames[i] = cardName;
    }
  }
  
  public JPanel getControls() {
    JPanel pnl = new JPanel();
    pnl.setLayout(new BoxLayout(pnl, BoxLayout.LINE_AXIS));
    
    btnNext = new JButton(NEXT);
    btnNext.addActionListener(this);
    btnNext.setActionCommand(NEXT);
    
    btnPrev = new JButton(PREV);
    btnPrev.addActionListener(this);
    btnPrev.setActionCommand(PREV);
    
    lblTime = new JLabel();
    
    pnl.add(btnPrev);
    pnl.add(Box.createRigidArea(new Dimension(10,10)));
    pnl.add(lblTime);
    pnl.add(Box.createRigidArea(new Dimension(10,10)));
    pnl.add(btnNext);
    pnl.setAlignmentX(Component.CENTER_ALIGNMENT);
    return pnl;
  }
  
  /**
   * Create the GUI and show it.  For thread safety,
   * this method should be invoked from the
   * event-dispatching thread.
   */
  public void showGUI() {
    cardIndex = cardNames.length-1;
    long dateTime = Long.parseLong(cardNames[cardIndex]);
    String dateTimeString = dateFormat.format(new Date(dateTime));
    lblTime.setText(dateTimeString);
    
    CardLayout cl = (CardLayout)(cards.getLayout());
    cl.last(cards);
    btnPrev.setEnabled(cardNames.length > 1);
    btnNext.setEnabled(false);
    
    pack();
    setVisible(true);    
  }

  public void actionPerformed(ActionEvent e) {
    CardLayout cl = (CardLayout)(cards.getLayout());    
    if(e.getActionCommand().equals(NEXT)) {
      cardIndex++;
//      cl.next(cards);
    }
    else if(e.getActionCommand().equals(PREV)) {
      cardIndex--;
//      cl.previous(cards);
    }
    
    btnNext.setEnabled((cardIndex+1 < cardNames.length));
    btnPrev.setEnabled((cardIndex > 0));
    
//    CardLayout cl = (CardLayout)(cards.getLayout());    
    cl.show(cards, cardNames[cardIndex]);
    
    long dateTime = Long.parseLong(cardNames[cardIndex]);
//System.out.println("cell table time: "+dateTime);
    String dateTimeString = dateFormat.format(new Date(dateTime));
    lblTime.setText(dateTimeString);
  }
}
